package com.icloud.article.boot.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.icloud.article.boot.dto.IMBatchInviteDto;
import com.icloud.article.boot.dto.IMInviteDto;
import com.icloud.article.boot.dto.IMInviteHandleDto;
import com.icloud.article.boot.dto.IMInvitePageDto;
import com.icloud.article.boot.mapper.TIMInviteMessageMapper;
import com.icloud.article.boot.model.TIMInviteMessage;
import com.icloud.article.boot.service.ITIMInviteMessageService;
import com.icloud.article.boot.vo.IMInviteVo;
import com.icloud.common.core.api.ResultCode;
import com.icloud.common.database.enums.IMMessageTypeEnum;
import com.icloud.common.database.enums.TFEnum;
import com.icloud.common.database.mapper.AppCustomerMapper;
import com.icloud.common.web.exception.Asserts;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ITIMInviteMessageServiceImpl extends ServiceImpl<TIMInviteMessageMapper, TIMInviteMessage> implements ITIMInviteMessageService {
    @Autowired
    private AppCustomerMapper appCustomerMapper;
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean invite(IMBatchInviteDto batchDto) {
        List<IMInviteDto> dtoList = batchDto.getInviteDtoList();
        if(CollectionUtil.isEmpty(dtoList)){
            return false;
        }

        // 申请加好友
        List<IMInviteDto> friendApplyList = dtoList.stream().filter(dto->
                IMMessageTypeEnum.isFriendApply(dto.getMessageType())
                        // 剔除自己加自己的情况
                        && ! dto.getApplicantId().equals(dto.getCustomerId())
        ).collect(Collectors.toList());

        // 申请入群
        List<IMInviteDto> joinGroupList = dtoList.stream().filter(dto->
                IMMessageTypeEnum.isJoinGroupApply(dto.getMessageType())
                        // 剔除没有groupId的
                        && StringUtils.isNotBlank(dto.getGroupId())
        ).collect(Collectors.toList());

        // 拉人加群申请
        List<IMInviteDto> inviteGroupList = dtoList.stream().filter(dto->
                IMMessageTypeEnum.isInviteGroup(dto.getMessageType())
                        // 剔除没有groupId的
                        && StringUtils.isNotBlank(dto.getGroupId())
        ).collect(Collectors.toList());

        List<Long> customerIdList = dtoList.stream().map(IMInviteDto::getCustomerId).collect(Collectors.toList());
        List<Long> applicantIdList = dtoList.stream().map(IMInviteDto::getApplicantId).collect(Collectors.toList());
        List<String> groupIdList = dtoList.stream().map(IMInviteDto::getGroupId).collect(Collectors.toList());
        LambdaQueryWrapper<TIMInviteMessage> inviteQuery = new LambdaQueryWrapper<>();
        inviteQuery.in(TIMInviteMessage::getCustomerId, customerIdList);
        inviteQuery.in(TIMInviteMessage::getApplicantId, applicantIdList);
        inviteQuery.and(i->i.in(TIMInviteMessage::getGroupId, groupIdList).or().isNull(TIMInviteMessage::getGroupId));
        List<TIMInviteMessage> existList = baseMapper.selectList(inviteQuery);

        if(CollectionUtil.isEmpty(existList)) {
            List<IMInviteDto> emptyInitList = new ArrayList<>();
            emptyInitList.addAll(friendApplyList);
            emptyInitList.addAll(joinGroupList);
            emptyInitList.addAll(inviteGroupList);

            List<TIMInviteMessage> list = emptyInitList.stream().map(dto -> {
                TIMInviteMessage timInviteMessage = TIMInviteMessage.builder().build();
                BeanUtils.copyProperties(dto, timInviteMessage);
                return timInviteMessage;
            }).collect(Collectors.toList());

            return saveBatch(list);
        }
        List<Long> existCustomerIdList = existList.stream().map(TIMInviteMessage::getCustomerId).collect(Collectors.toList());
        List<Long> existApplicantIdList = existList.stream().map(TIMInviteMessage::getApplicantId).collect(Collectors.toList());
        List<String> existGroupIdList = existList.stream().map(TIMInviteMessage::getGroupId).collect(Collectors.toList());

        // 剔除已存在的申请加好友记录
        List<IMInviteDto> newFriendApplyList = friendApplyList.stream().filter(dto->
                !( existCustomerIdList.contains(dto.getCustomerId()) && existApplicantIdList.contains(dto.getApplicantId()) )
        ).collect(Collectors.toList());

        // 已存在的申请加好友记录
        List<IMInviteDto> existsFriendApplyList = friendApplyList.stream().filter(dto->
                ( existCustomerIdList.contains(dto.getCustomerId()) && existApplicantIdList.contains(dto.getApplicantId()) )
        ).collect(Collectors.toList());

        // 剔除已存在的申请入群记录
        List<IMInviteDto> newJoinGroupList = joinGroupList.stream().filter(dto->
                !( existCustomerIdList.contains(dto.getCustomerId())
                        && existApplicantIdList.contains(dto.getApplicantId())
                        && existGroupIdList.contains(dto.getGroupId()) )
        ).collect(Collectors.toList());

        // 已存在的申请入群记录
        List<IMInviteDto> existsJoinGroupList = joinGroupList.stream().filter(dto->
                ( existCustomerIdList.contains(dto.getCustomerId())
                        && existApplicantIdList.contains(dto.getApplicantId())
                        && existGroupIdList.contains(dto.getGroupId()) )
        ).collect(Collectors.toList());

        // 剔除已存在的拉人加群申请记录
        List<IMInviteDto> newInviteGroupList = inviteGroupList.stream().filter(dto->
                !( existCustomerIdList.contains(dto.getCustomerId())
                        && existApplicantIdList.contains(dto.getApplicantId())
                        && existGroupIdList.contains(dto.getGroupId()) )
        ).collect(Collectors.toList());

        // 剔除已存在的拉人加群申请记录
        List<IMInviteDto> existsInviteGroupList = inviteGroupList.stream().filter(dto->
                ( existCustomerIdList.contains(dto.getCustomerId())
                        && existApplicantIdList.contains(dto.getApplicantId())
                        && existGroupIdList.contains(dto.getGroupId()) )
        ).collect(Collectors.toList());

        List<IMInviteDto> newDtoList = new ArrayList<>();
        newDtoList.addAll(newFriendApplyList);
        newDtoList.addAll(newJoinGroupList);
        newDtoList.addAll(newInviteGroupList);

        List<IMInviteDto>  existDtoList = new ArrayList<>();
        existDtoList.addAll(existsFriendApplyList);
        existDtoList.addAll(existsJoinGroupList);
        existDtoList.addAll(existsInviteGroupList);

        List<TIMInviteMessage> newList = newDtoList.stream().map(dto->{
            TIMInviteMessage timInviteMessage = TIMInviteMessage.builder().build();
            BeanUtils.copyProperties(dto, timInviteMessage);
            return timInviteMessage;
        }).collect(Collectors.toList());

        List<TIMInviteMessage> updateList = new ArrayList<>();
        for(TIMInviteMessage entity : existList){
            for(IMInviteDto dto : existDtoList){
                Long dtoCustomerId = dto.getCustomerId();
                Long dtoApplicantId = dto.getApplicantId();
                String dtoGroupId = dto.getGroupId();
                String dtoMessageType = dto.getMessageType();
                Long eCustomerId = entity.getCustomerId();
                Long eApplicantId = entity.getApplicantId();
                String eGroupId = entity.getGroupId();
                String eMessageType = entity.getMessageType();
                if(dtoMessageType.equalsIgnoreCase(eMessageType)) {
                    if (dtoCustomerId.equals(eCustomerId) && dtoApplicantId.equals(eApplicantId)) {
                        if(IMMessageTypeEnum.isFriendApply(dtoMessageType) ||
                                (dtoGroupId.equalsIgnoreCase(eGroupId)) ){
                            TIMInviteMessage msg = TIMInviteMessage.builder().build();
                            BeanUtils.copyProperties(dto, msg);
                            msg.setId(entity.getId());
                            msg.setIsAccept("");
                            updateList.add(msg);
                        }
                    }
                }
            }
        }

        boolean result = false;
        if(!CollectionUtils.isEmpty(newList)) {
            result = saveBatch(newList);
        }
        if(!CollectionUtils.isEmpty(updateList)) {
            result = updateBatchById(updateList);
        }
        return result;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean handle(IMInviteHandleDto dto) {
        Long messageId = dto.getMessageId();
        TIMInviteMessage message = baseMapper.selectById(messageId);
        Asserts.fail(null==message, ResultCode.DATA_NOT_EXISTS);

        TFEnum tfEnum = TFEnum.byCode(dto.getIsAccept());
        Asserts.fail(null== tfEnum, ResultCode.VALIDATE_FAILED);
        TIMInviteMessage update = TIMInviteMessage.builder().build();
        update.setId(messageId);
        update.setIsAccept(tfEnum.getCode());
        baseMapper.updateById(update);
        return true;
    }

    @Override
    public Page<IMInviteVo> invitePage(IMInvitePageDto dto) {
        IPage<TIMInviteMessage> page = Page.of(dto.getCurrent(), dto.getPageSize());
        IPage<TIMInviteMessage> messagePage = baseMapper.selectPage(page, new LambdaQueryWrapper<TIMInviteMessage>()
                .eq(TIMInviteMessage::getCustomerId, dto.getCustomerId())
                .orderByDesc(TIMInviteMessage::getCreatedAt)
        );
        List<IMInviteVo> voList = messagePage.getRecords().stream().map(t->{
            IMInviteVo vo = new IMInviteVo();
            BeanUtils.copyProperties(t, vo);
            vo.setMessageId(t.getId());
            return vo;
        }).collect(Collectors.toList());

        Page<IMInviteVo> voPage = new Page<>();
        BeanUtils.copyProperties(page, voPage);
        voPage.setRecords(voList);
        return voPage;
    }
}
